package utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.Vector;


public class MatrixUtils {
	
	static final String NO_SOL_MSG = "NOSOL";
	
	
	public static boolean increment(int[] vec){
		boolean res = false;
		for (int i = vec.length-1; i >=0  && !res; i--){
			if (vec[i] == 0){
				res = true;
				for (int j = i; j <vec.length; j++){
					vec[j] = bitFilp(vec[j]);
				}
				break;
			}
		}
		return res;
	}
	
	
	public static boolean increment(int[][] matrix){
		boolean res = false;
		for (int i = matrix.length - 1; i >= 0; i--){
			if (increment(matrix[i])){
				res = true;
				for (int j = i+1; j <matrix.length; j++){
					zero(matrix[j]);
				}
				break;
			}
		}
		
		return res;
	}
	
	public static int bitFilp(int bit){
		if (bit == 0) return 1;
		return 0;
	}
	static void zero(int[] vec){
		for (int i = 0; i < vec.length; i++){
			vec[i] = 0;
		}
	}
	
	public static String print(int[] vec){
		String res = "";
		if (vec == null) return "null";
		for (int i = 0; i < vec.length; i++){
			res+=vec[i];
			res+=',';
		}
		return res;
	}
	
	public static String print(int[][] matrix){
		String res = "{";
		for (int i = 0; i < matrix.length; i++){
			res+=print(matrix[i]);
			res+= "\n";
		}
		res += "}";
		return res;
	}
	


	public static void writeMapFile(int[][] map, String mapFileName) {
		FileWriter fw =null;
		try {
			File f = new File(mapFileName);
			fw = new FileWriter(f);
			for (int i = 0; i < map.length; i++){
				for (int j = 0; j < map.length; j++){
					String litNum = map[i][j] +"";
					fw.write("cell " + (i+1) +" " + (j+1) + " " + litNum + "\n");
				}
			}
			
			
			fw.flush();
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if (fw != null){
				try {
					fw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}		
	}
	
	public static void printColoring(int[][] coloring, long time) {
		int dimension = coloring.length;
		if (time>-1)
			System.out.println("finished in : " + time +" ms");
		for (int i = 0; i < dimension; i++){
			System.out.print("|");
			for (int j = 0; j< dimension; j++){
				System.out.print(coloring[i][j] + "|");
			}
			System.out.println();
		}
	}
	
	public static void printSolution(int[][] map, boolean[] sol, long time) {
		int dimention = map.length;
		if (sol != null && sol.length>0){
			System.out.println("finished in : " + time +" ms");
			for (int i = 0; i < dimention; i++){
				for (int j = 0; j< dimention; j++){
					System.out.print(sol[map[i][j]]?"1":"0");
				}
				System.out.println();
			}
			
		}else{
			if (sol==null){
				System.out.println("Time Out!! add more time");
			}else System.out.println("there is no solution");
		}
	}

	public static void saveColoringToFile(int[][] coloring, String solFileName) {
		int dimention = coloring.length;		
		FileWriter fw =null;
		try {
			File f = new File(solFileName);
			fw = new FileWriter(f);
			for (int i = 0; i < dimention; i++){
				for (int j = 0; j< dimention; j++){
					String litNum = Integer.toString(coloring[i][j]);
					fw.write("cell " + (i+1) +" " + (j+1) + " " + litNum + "\n");
				}
			}
			fw.flush();
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if (fw != null){
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}		
	}
	
	public static void saveSolutionToFile(int[][] map, boolean[] sol,
			String solFileName) {
		int dimention = map.length;		
		FileWriter fw =null;
		try {
			File f = new File(solFileName);
			fw = new FileWriter(f);
			if (sol.length >0){
				for (int i = 0; i < dimention; i++){
					for (int j = 0; j< dimention; j++){
						String litNum = sol[map[i][j]]?"1":"0";
						fw.write("cell " + (i+1) +" " + (j+1) + " " + litNum + "\n");
					}
				}
			}else{
				fw.write(NO_SOL_MSG);
			}
			fw.flush();
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if (fw != null){
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}		
	}


	public static int[][] loadMapFile(String mapFileName) {
		int[][] res = null;
		File f = new File(mapFileName);
		FileReader fr = null;
		boolean isFaild = false;
		int lineCounter = 1;
		Vector<int[]> vectorMap = new Vector<int[]>();
		try{
			fr = new FileReader(f);
			BufferedReader br = new BufferedReader(fr);
			String line;
			
			while ((line = br.readLine()) != null){
				String[] words = line.split(" ");
				if (words.length < 4){
					isFaild = true;
					break;
				}else{
					int[] l = {Integer.parseInt(words[3]), Integer.parseInt(words[1]),Integer.parseInt(words[2])};
					vectorMap.add(l);
					lineCounter++;
				}
			}
			
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			if (fr!= null){
				try {
					fr.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (isFaild){
				throw new RuntimeException("there was an Error reading map file: \"" + mapFileName + "\" in line " + lineCounter);
			}else{
				int dimention = (int) Math.sqrt(lineCounter-1);
				res = new int[dimention][dimention];
				Iterator<int[]> it = vectorMap.iterator();
				while (it.hasNext()){
					int[] l = it.next();
					res[l[1]-1][l[2]-1] = l[0];
				}
			}
		}
		return res;
	}
}
